<?php

class UpgradeCtrlLogic
{
public function CreateToken()
{
$r = array(
'token'=>'#__THIS_IS_TOKEN__#',
'url'=>'#__THIS_IS_UPGRADE_URL__#'
);
$r['token'] = $token = md5((string)microtime(true));
$args = array(
'locSysURL'=>ini('settings.site_url'),
'locApiURL'=>ini('settings.site_url').'/index.php?mod=apiz&code=upgrade',
'locApiToken'=>$token,
'locVersion'=>SYS_VERSION,
'locCharset'=>ini('settings.charset'),
'locBuild'=>SYS_BUILD,
'locRelease'=>SYS_RELEASE,
);
$argString = serialize($args);
$md5 = md5($argString);
$argString = base64_encode($argString);
$r['url'] = $srvParser = $this->UpdateServerURL().'&data='.$argString.'&md5='.$md5;
$this->TokenMe($token);
return $r;
}
public function TokenMe($token = null)
{
$file = DATA_PATH.'upgrade.manual.token.php';
if (is_null($token))
{
if (is_file($file))
{
if (time() -filemtime($file) <86400)
{
include $file;
return $__upgrade_manual_token;
}
}
return '#TOKEN_NULL#';
}
if ($token === false)
{
is_file($file) &&unlink($file);
return '#DELETE_OK#';
}
if ($token)
{
$token = (string)$token;
$c = '<?php /* TOKEN @time '.date('Y-m-d H:i:s').' */ $__upgrade_manual_token = "'.$token.'"; ?>';
file_put_contents($file,$c);
return '#WRITE_OK#';
}
return '#OPC_ERROR#';
}
public function APISelector()
{
loadInstance('logic.upgrade.api.selector','UpgradeCtrlLogic_APISelector')->Selector();
}
private function UpdateServerURL()
{
# http:
return base64_decode('aHR0cDovL3VwZGF0ZS5jZW53b3IuY29tL3VwZ3JhZGUucGhwP3Byb2Nlc3NvciZwaWQ9MQ==');
}
############################################
####   升级操作
############################################
public function zip2web($zipFile,$webDir)
{
include_once(FUNCTION_PATH.'zip.moyo.php');
return zip2web($zipFile,$webDir);
}
public function upgrade2start()
{
@touch(CACHE_PATH.'upgrade.lock');
}
public function web2backup($upsDir,$bakDir)
{
$files = handler('io')->ReadDir($upsDir,1);
$error_file_list = array();
foreach ($files as $i =>$upfile_path)
{
$baseFileName = substr($upfile_path,strlen($upsDir));
list($baseDIR) = explode('/',$baseFileName);
if ($baseDIR == '__upgrade__') continue;
$webfile_path = handler('io')->initPath(ROOT_PATH.$baseFileName);
$bakfile_path = handler('io')->initPath($bakDir.$baseFileName);
if (is_file($webfile_path))
{
$r = handler('io')->CopyFile($webfile_path,dirname($bakfile_path));
if ($r)
{
if (md5_file($webfile_path) != md5_file($bakfile_path))
{
$error_file_list['backup_md5_error'][$webfile_path] = $bakfile_path;
}
}
else
{
$error_file_list['backup_write_error'][$webfile_path] = $bakfile_path;
}
}
}
$error_file_type = array(
'backup_md5_error'=>array('name'=>'文件备份错误，备份后的内容和网站原内容不一致'),
'backup_write_error'=>array('name'=>'文件备份错误，无法写入备份文件')
);
$error_found = 'ok';
foreach ($error_file_list as $type =>$file_list)
{
$error_found .= '<fieldset><legend>'.$error_file_type[$type]['name'].'</legend><ul>';
foreach ($file_list as $op_file =>$or_file)
{
$error_found .= '<li>'.$or_file.'</li>';
}
$error_found .= '</ul></fieldset>';
}
return $error_found;
}
public function web2upgrade($upsDir,$webDir)
{
$files = handler('io')->ReadDir($upsDir,1);
$error_file_list = array();
foreach ($files as $i =>$upfile_path)
{
$baseFileName = substr($upfile_path,strlen($upsDir));
list($baseDIR) = explode('/',$baseFileName);
if ($baseDIR == '__upgrade__') continue;
$webfile_path = handler('io')->initPath($webDir.$baseFileName);
if (!$this->upgraded2setting($upfile_path,$webfile_path,$webDir))
{
$r = handler('io')->CopyFile($upfile_path,dirname($webfile_path));
if ($r)
{
if (md5_file($upfile_path) != md5_file($webfile_path))
{
$error_file_list['upgrade_md5_error'][$upfile_path] = $webfile_path;
}
}
else
{
$error_file_list['upgrade_write_error'][$upfile_path] = $webfile_path;
}
}
}
$error_file_type = array(
'upgrade_md5_error'=>array('name'=>'文件升级错误，升级后的网站文件和升级源文件内容不一致'),
'upgrade_write_error'=>array('name'=>'文件升级错误，无法写入升级文件')
);
$error_found = 'ok';
foreach ($error_file_list as $type =>$file_list)
{
$error_found .= '<fieldset><legend>'.$error_file_type[$type]['name'].'</legend><ul>';
foreach ($file_list as $op_file =>$or_file)
{
$error_found .= '<li>'.$or_file.'</li>';
}
$error_found .= '</ul></fieldset>';
}
return $error_found;
}
public function upgrade2data($upsDir)
{
$upgrade_script_dir = $upsDir.'__upgrade__/';
if(is_dir($upgrade_script_dir)) {
$files = handler('io')->ReadDir($upgrade_script_dir);
foreach ($files as $i =>$path)
{
include $path;
}
}
}
public function upgrade2update($upsDir,$webDir)
{
$const_file = 'setting/constants.php';
$copy_from = $upsDir.$const_file;
$copy_to = $webDir.$const_file;
handler('io')->CopyFile($copy_from,dirname($copy_to));
}
public function upgrade2finish()
{
clearcache();
}
public function upgrade2clear($upcName)
{
$zipFile = DATA_PATH.'upgrade/'.$upcName.'.zip';
is_file($zipFile) &&unlink($zipFile);
$upsDir = DATA_PATH.'upgrade/'.$upcName.'/';
is_dir($upsDir) &&IoHandler::RemoveDir($upsDir);
}
private function upgraded2setting($upfile,$webfile,$webDir = ROOT_PATH)
{
$basefile = substr($webfile,strlen($webDir));
list($dir_1st,$file) = explode('/',$basefile);
if ($dir_1st != 'setting')
{
return false;
}
if (!is_file($webfile))
{
return false;
}
if (in_array($file,array('admin_left_menu.php','admin_privs.php','isearcher.php')))
{
return false;
}
if ($file == 'constants.php')
{
return true;
}
$cfName = handler('io')->BaseName($webfile,true);
include $upfile;
if (empty($config[$cfName])) return false;
$cfNew = $config[$cfName];
include $webfile;
if (empty($config[$cfName])) return false;
$cfOld = $config[$cfName];
$cfMix = $this->array_mix($cfOld,$cfNew);
if (md5(serialize($cfOld)) == md5(serialize($cfMix)))
{
return true;
}
file_put_contents($webfile,'<?php /* upgrade Finish @time '.date('Y-m-d H:i:s').' */ $config["'.$cfName.'"] = '.var_export($cfMix,true).' ; ?>');
return true;
}
private function array_mix($aSrc,$aAppend)
{
$aMix = array();
foreach ($aAppend as $key =>$val)
{
if (is_array($val))
{
$aMix[$key] = $this->array_mix($aSrc[$key],$val);
}
elseif (isset($aSrc[$key]))
{
$aMix[$key] = $aSrc[$key];
}
else
{
$aMix[$key] = $val;
}
}
return $aMix;
}
}
class UpgradeCtrlLogic_APISelector
{
public function Selector()
{
$this->checkToken();
$apiName = get('api','txt');
if (method_exists($this,$apiName))
{
exit((string)$this->$apiName());
}
exit('API UNKNOWN');
}
private function test()
{
exit('ok');
}
private function start()
{
$upcName = get('upcn','txt');
$webDir = ROOT_PATH;
$bakDir = handler('io')->initPath($webDir.'backup/'.SYS_VERSION.'-'.SYS_BUILD.'/');
logic('upgrade')->upgrade2start();
$zipFile = DATA_PATH.'upgrade/'.$upcName.'.zip';
$upsDir = DATA_PATH.'upgrade/'.$upcName.'/';
if (is_file($zipFile))
{
$r = logic('upgrade')->zip2web($zipFile,$upsDir);
$r['__extract_error__'] === true &&exit($r['__error_string__']);
}
is_dir($upsDir) ||exit('升级文件不存在！');
is_file($upsDir.'setting/constants.php') ||exit('升级文件不完整，请检查！');
$r = logic('upgrade')->web2backup($upsDir,$bakDir);
$r == 'ok'||exit($r);
$r = logic('upgrade')->web2upgrade($upsDir,$webDir);
$r == 'ok'||exit($r);
logic('upgrade')->upgrade2data($upsDir);
logic('upgrade')->upgrade2update($upsDir,$webDir);
logic('upgrade')->upgrade2clear($upcName);
logic('upgrade')->upgrade2finish();
exit('ok');
}
private function finish()
{
logic('upgrade')->TokenMe(false);
exit('ok');
}
private function checkToken()
{
$tokenSys = logic('upgrade')->TokenMe();
$tokenUser = get('token','txt');
if ($tokenUser != $tokenSys)
{
exit('升级令牌错误！');
}
}
}

?>
